package com.fangyi.yunmusic.service.impl;

import com.fangyi.yunmusic.config.ResourceConfig;
import com.fangyi.yunmusic.exception.YunMusicException;
import com.fangyi.yunmusic.mapper.*;
import com.fangyi.yunmusic.pojo.*;
import com.fangyi.yunmusic.pojo.vo.SongVO;
import com.fangyi.yunmusic.service.SongService;
import com.fangyi.yunmusic.utils.FileServerUtils;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.n3r.idworker.Id;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.*;

@Service
public class SongServiceImpl implements SongService{

    @Autowired
    private PlaylistMapper playlistMapper;

    @Autowired
    private SongMapper songMapper;

    @Autowired
    private PlaylistHasSongMapper playlistHasSongMapper;

    @Autowired
    private AlbumHasSongMapper albumHasSongMapper;

    @Autowired
    private ArtistHasAlbumMapper artistHasAlbumMapper;

    @Autowired
    private AlbumMapper albumMapper;

    @Autowired
    private ArtistMapper artistMapper;

    @Autowired
    private ResourceConfig resourceConfig;

    @Override
    public void addSong(Song song, String albumId) {
        song.setId(Id.nextString());
        song.setPublishTime(new Date());
        songMapper.insertSelective(song);

        AlbumHasSong albumHasSong = new AlbumHasSong();
        albumHasSong.setAlbumId(albumId);
        albumHasSong.setSongId(song.getId());
        albumHasSong.setId(Id.nextString());
        albumHasSongMapper.insert(albumHasSong);
    }

    @Override
    public void deleteSong(String songId) {
        Song song=songMapper.selectByPrimaryKey(songId);
        if(song==null){
            throw new YunMusicException("歌曲ID不存在！");
        }
        Example plhsExample = new Example(PlaylistHasSong.class);
        Example.Criteria plhsCriteria = plhsExample.createCriteria();
        plhsCriteria.andEqualTo("songId", songId);
        playlistHasSongMapper.deleteByExample(plhsExample);

        Example ahsExample = new Example(PlaylistHasSong.class);
        Example.Criteria ahsCriteria = ahsExample.createCriteria();
        ahsCriteria.andEqualTo("songId", songId);
        albumHasSongMapper.deleteByExample(ahsExample);

        songMapper.deleteByPrimaryKey(songId);
    }

    @Override
    public List<SongVO> selectSongByPlaylistId(String playlistId) {

        Example example = new Example(PlaylistHasSong.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("playlistId", playlistId);
        List<PlaylistHasSong> playlistHasSongs = playlistHasSongMapper.selectByExample(example);

        List<String> songIds = playlistHasSongs.stream().map(PlaylistHasSong::getSongId).collect(toList());
        if (songIds.size() == 0) {
            return new ArrayList<>();   // 不进行无意义的数据库查询，直接返回空列表
        }
        List<Song> songs = songMapper.selectSongByIds(songIds);
        List<SongVO> songVOs = convertTOSongVOs(songs, songIds);
        return songVOs;
    }

    @Override
    public List<SongVO> selectSongByAlbumId(String albumId) {
        Example example = new Example(AlbumHasSong.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("albumId", albumId);
        List<AlbumHasSong> albumHasSongs = albumHasSongMapper.selectByExample(example);

        List<String> songIds = albumHasSongs.stream().map(AlbumHasSong::getSongId).collect(toList());
        if (songIds.size() == 0) {
            return new ArrayList<>();
        }

        List<Song> songs = songMapper.selectSongByIds(songIds);

        List<SongVO> songVOs = convertTOSongVOs(songs, songIds);
        return songVOs;
    }

    @Override
    public SongVO getSongDetail(String songId) {
        Song song = songMapper.selectByPrimaryKey(songId);
        if (song == null) {
            throw new YunMusicException("歌曲不存在");
        }
        return convertToSongVO(song);
    }

    @Override
    public List<SongVO> selectSongByArtistId(String artistId) {
        if(artistMapper.selectByPrimaryKey(artistId)==null)
            throw new YunMusicException("歌手ID不存在！");
        Example example=new Example(ArtistHasAlbum.class);
        Example.Criteria criteria=example.createCriteria();
        criteria.andEqualTo("artistId",artistId);
        List<String > albumIds=artistHasAlbumMapper.selectByExample(example).stream().map(ArtistHasAlbum::getAlbumId).collect(toList());
        List<SongVO> songVOS=new ArrayList<>();
        for(String albumId:albumIds){
            songVOS.addAll(selectSongByAlbumId(albumId));
        }
        return songVOS;
    }

    @Override
    public Integer getSongCount() {
        return songMapper.getSongCount();
    }

    private SongVO convertToSongVO(Song song) {
        SongVO songVO = new SongVO();
        BeanUtils.copyProperties(song, songVO);
        songVO.setSongUrl(resourceConfig.getSongUrl(song.getSongUrlId()));
        // 得到歌曲对应的专辑
        Example example = new Example(AlbumHasSong.class);
        example.createCriteria().andEqualTo("songId", song.getId());
        AlbumHasSong albumHasSong = albumHasSongMapper.selectOneByExample(example);
        Album album = albumMapper.selectByPrimaryKey(albumHasSong.getAlbumId());
        SongVO.SongAlbum songAlbum = new SongVO.SongAlbum();
        BeanUtils.copyProperties(album, songAlbum);
        songAlbum.setPicUrl(FileServerUtils.getAlbumCoverUrl(resourceConfig.getFileServer(), songAlbum.getPicUrlId()));
        songVO.setSongAlbum(songAlbum);
        // 得到专辑对应的歌手们
        Example exampleForArtists = new Example(ArtistHasAlbum.class);
        exampleForArtists.createCriteria().andEqualTo("albumId", album.getId());
        List<ArtistHasAlbum> artistHasAlbums = artistHasAlbumMapper.selectByExample(exampleForArtists);
        List<String> artistIds = artistHasAlbums.stream().map(ArtistHasAlbum::getArtistId).collect(toList());
        List<Artist> artists;
        if (artistIds.size() == 0) {
            artists = new ArrayList<>();
        } else {
            artists = artistMapper.selectArtistByIds(artistIds);
        }
        List<SongVO.SongArtist> songArtists = artists.stream().map(artist -> {
            SongVO.SongArtist songArtist = new SongVO.SongArtist();
            BeanUtils.copyProperties(artist, songArtist);
            songArtist.setPicUrl(resourceConfig.getArtistPicUrl(artist.getPicUrlId()));
            return songArtist;
        }).collect(toList());
        songVO.setSongArtists(songArtists);
        return songVO;
    }

    public List<SongVO> convertTOSongVOs(List<Song> songs, List<String> songIds) {
        // 得到 专辑--歌曲 关系表
        List<AlbumHasSong> albumHasSongs = albumHasSongMapper.selectAlbumHasSongBySongIds(songIds);
        // 得到专辑ID列表
        List<String> albumIds = albumHasSongs.stream().map(AlbumHasSong::getAlbumId).collect(toList());
        // 得到map:专辑ID->专辑Object
        Map<String, Album> albumMap = albumMapper.selectAlbumByIds(albumIds).stream().collect(toMap(Album::getId, album -> album));
        // 得到map:歌曲ID->专辑
        Map<String, Album> songId2AlbumMap = albumHasSongs.stream()
                .collect(toMap(AlbumHasSong::getSongId, albumHasSong -> albumMap.get(albumHasSong.getAlbumId())));

        // 得到 歌手--专辑 关系表
        List<ArtistHasAlbum> artistHasAlbums = artistHasAlbumMapper.selectArtistHasAlbumByAlbumIds(albumIds);
        // 得到歌手ID列表
        List<String> artistIds = artistHasAlbums.stream().map(ArtistHasAlbum::getArtistId).collect(toList());
        // 得到map:歌手ID->歌手Object
        Map<String, Artist> artistMap = artistMapper.selectArtistByIds(artistIds).stream().collect(toMap(Artist::getId, artist -> artist));

        // 得到map:专辑ID->SongArtist List
        Multimap<String, SongVO.SongArtist> albumId2ArtistMultiMap = ArrayListMultimap.create();
        artistHasAlbums.forEach(artistHasAlbum -> {
            if (artistMap.get(artistHasAlbum.getArtistId()) != null) {
                SongVO.SongArtist songArtist = new SongVO.SongArtist();
                BeanUtils.copyProperties(artistMap.get(artistHasAlbum.getArtistId()), songArtist);
                albumId2ArtistMultiMap.put(artistHasAlbum.getAlbumId(), songArtist);
            }
        });
        // 得到map:歌曲ID->SongArtist List
        Map<String, List<SongVO.SongArtist>> songId2ArtistListMap = albumHasSongs.stream()
                .collect(toMap(AlbumHasSong::getSongId, albumHasSong ->
                        (List<SongVO.SongArtist>) albumId2ArtistMultiMap.get(albumHasSong.getAlbumId())));

        // song -> songVO
        List<SongVO> songVOs = songs.stream().map(song -> {
            SongVO songVO = new SongVO();
            BeanUtils.copyProperties(song, songVO);
            songVO.setSongUrl(FileServerUtils.getSongUrl(resourceConfig.getFileServer(), song.getSongUrlId()));

            if (songId2AlbumMap.get(song.getId()) != null) {
                SongVO.SongAlbum songAlbum = new SongVO.SongAlbum();
                BeanUtils.copyProperties(songId2AlbumMap.get(song.getId()), songAlbum);
                songAlbum.setPicUrl(FileServerUtils.getAlbumCoverUrl(resourceConfig.getFileServer(), songAlbum.getPicUrlId()));
                songVO.setSongAlbum(songAlbum);
            }
            if (songId2ArtistListMap.get(song.getId()) != null) {
                songVO.setSongArtists(songId2ArtistListMap.get(song.getId()));
            }

            return songVO;
        }).collect(toList());

        return songVOs;
    }
}
